home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / filedir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-07  |  24.9 KB  |  1,071 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. #include "cf.defs.h"
  28. #include "cf.extern.h"
  29.  
  30.  
  31. /*********************************************************************/
  32.  
  33. IsHomeDir(name)
  34.  
  35.       /* This assumes that the dir lies under mountpattern */
  36.  
  37. char *name;
  38.  
  39. { char *sp;
  40.   struct Item *ip;
  41.   int slashes;
  42.   
  43. if (VMOUNTLIST == NULL)
  44.    {
  45.    return (false);
  46.    } 
  47.  
  48. for (ip = VHOMEPATLIST; ip != NULL; ip=ip->next)
  49.    {
  50.    slashes = 0;
  51.  
  52.    for (sp = ip->name; *sp != '\0'; sp++)
  53.       {
  54.       if (*sp == '/')
  55.      {
  56.      slashes++;
  57.      }
  58.       }
  59.    
  60.    for (sp = name+strlen(name); (*(sp-1) != '/') && (sp >= name) && (slashes >= 0); sp--)
  61.       {
  62.       if (*sp == '/')
  63.      {
  64.      slashes--;
  65.      }
  66.       }
  67.  
  68.    /* Full comparison */
  69.    
  70.    if (WildMatch(ip->name,sp))
  71.       {
  72.       Debug("IsHomeDir(true)\n");
  73.       return(true);
  74.       }
  75.    }
  76.  
  77. Debug("IsHomeDir(false)\n");
  78. return(false);
  79. }
  80.  
  81.  
  82. /*********************************************************************/
  83.  
  84. EmptyDir(path)
  85.  
  86. char *path;
  87.  
  88. { DIR *dirh;
  89.   struct dirent *dirp;
  90.   int count = 0;
  91.   
  92. Debug2("cfengine: EmptyDir(%s)\n",path);
  93.  
  94. if ((dirh = opendir(path)) == NULL)
  95.    {
  96.    sprintf(OUTPUT,"Can't open directory %s\n",path);
  97.    CfLog(cferror,OUTPUT,"opendir");
  98.    return true;
  99.    }
  100.  
  101. for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  102.    {
  103.    if (!SensibleFile(dirp->d_name,path,NULL))
  104.       {
  105.       continue;
  106.       }
  107.  
  108.    count++;
  109.    }
  110.  
  111. closedir(dirh);
  112.  
  113. return (!count);
  114. }
  115.  
  116. /*********************************************************************/
  117.  
  118. RecursiveCheck(name,plus,minus,action,uidlist,gidlist,recurse,rlevel,ptr)
  119.  
  120. char *name;
  121. mode_t plus,minus;
  122. struct UidList *uidlist;
  123. struct GidList *gidlist;
  124. enum fileactions action;
  125. int recurse;
  126. int rlevel;
  127. struct File *ptr;
  128.  
  129. { DIR *dirh;
  130.   struct dirent *dirp;
  131.   char pcwd[bufsize];
  132.   struct stat statbuf;
  133.  
  134. if (recurse == -1)
  135.    {
  136.    return;
  137.    }
  138.  
  139. Debug("RecursiveCheck(%s,+%o,-%o)\n",name,plus,minus);
  140.  
  141. if ((dirh = opendir(name)) == NULL)
  142.    {
  143.    if (lstat(name,&statbuf) != -1)
  144.       {
  145.       CheckExistingFile(name,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
  146.       }
  147.    return;
  148.    }
  149.  
  150. for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
  151.    {
  152.    if (!SensibleFile(dirp->d_name,name,NULL))
  153.       {
  154.       continue;
  155.       }
  156.  
  157.    if (IgnoreFile(name,dirp->d_name,ptr->ignores))
  158.       {
  159.       continue;
  160.       }
  161.  
  162.    strcpy(pcwd,name);                                   /* Assemble pathname */
  163.    AddSlash(pcwd);
  164.  
  165.    if (BufferOverflow(pcwd,dirp->d_name))
  166.       {
  167.       return;
  168.       }
  169.  
  170.    strcat(pcwd,dirp->d_name);
  171.  
  172.    
  173.    if (TRAVLINKS)
  174.       {
  175.       if (stat(pcwd,&statbuf) == -1)
  176.          {
  177.          sprintf(OUTPUT,"RecursiveCheck was working on %s when this happened:\n",pcwd);
  178.      CfLog(cferror,OUTPUT,"stat");
  179.          continue;
  180.          }
  181.       }
  182.    else
  183.       {
  184.       if (lstat(pcwd,&statbuf) == -1)
  185.          {
  186.          sprintf(OUTPUT,"RecursiveCheck was working in %s when this happened:\n",pcwd);
  187.          CfLog(cferror,OUTPUT,"lstat");
  188.          continue;
  189.          }
  190.       }
  191.  
  192.    if (S_ISLNK(statbuf.st_mode))            /* should we ignore links? */
  193.       {
  194.       CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
  195.       continue;
  196.       }
  197.  
  198.    if (S_ISDIR(statbuf.st_mode))
  199.       {
  200.       if (IsMountedFileSystem(&statbuf,pcwd,rlevel))
  201.          {
  202.          continue;
  203.          }
  204.       else
  205.          {
  206.          if ((ptr->recurse > 1) || (ptr->recurse == INFINITERECURSE))
  207.             {
  208.             CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
  209.             RecursiveCheck(pcwd,plus,minus,action,uidlist,gidlist,recurse-1,rlevel+1,ptr);
  210.             }
  211.          else
  212.             {
  213.             CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
  214.             }
  215.          }
  216.       }
  217.    else
  218.       {
  219.       CheckExistingFile(pcwd,plus,minus,action,uidlist,gidlist,&statbuf,ptr,ptr->acl_aliases);
  220.       }
  221.    }
  222.  
  223. closedir(dirh);
  224. }
  225.  
  226.  
  227. /*********************************************************************/
  228.  
  229. CheckExistingFile(file,plus,minus,action,uidlist,gidlist,dstat,ptr,acl_aliases)
  230.  
  231. char *file;
  232. mode_t plus,minus;
  233. struct UidList *uidlist;
  234. struct GidList *gidlist;
  235. enum fileactions action;
  236. struct stat *dstat;
  237. struct File *ptr;
  238. struct Item *acl_aliases;
  239.  
  240. { mode_t newperm = dstat->st_mode;
  241.   int amroot = true, fixmode = true;
  242.   char digest[17];
  243. #if defined HAVE_CHFLAGS
  244.   u_long newflags;
  245. #endif
  246.  
  247. Debug("%s: Checking fs-object %s\n",VPREFIX,file);
  248.  
  249. #if defined HAVE_CHFLAGS
  250. if (ptr != NULL)
  251.    {
  252.    Debug("CheckExistingFile(+%o,-%o,+%o,-%o)\n",plus,minus,ptr->plus_flags,ptr->minus_flags);
  253.    }
  254. else
  255.    {
  256.    Debug("CheckExistingFile(+%o,-%o)\n",plus,minus);
  257.    }
  258. #else
  259. Debug("CheckExistingFile(+%o,-%o)\n",plus,minus);
  260. #endif
  261.  
  262. if (ptr != NULL)
  263.    {
  264.    if (IgnoredOrExcluded(files,file,ptr->inclusions,ptr->exclusions))
  265.       {
  266.       Debug("Skipping excluded file %s\n",file);
  267.       return;
  268.       }
  269.    }
  270.  
  271. if (getuid() != 0)                            
  272.    {
  273.    amroot = false;
  274.    }
  275.  
  276.  /* directories must have x set if r set, regardless  */
  277.  
  278.  
  279. newperm = (dstat->st_mode & 07777) ;
  280. newperm |= plus;
  281. newperm &= ~minus;
  282.  
  283. if (S_ISREG(dstat->st_mode) && (action == fixdirs || action == warndirs)) 
  284.    {
  285.    Debug("Regular file, returning...\n");
  286.    return;
  287.    }
  288.  
  289. if (S_ISDIR(dstat->st_mode))  
  290.    {
  291.    if (action == fixplain || action == warnplain)
  292.       {
  293.       return;
  294.       }
  295.  
  296.    Debug("Directory...fixing x bits\n");
  297.  
  298.    if (newperm & S_IRUSR)
  299.       {
  300.       newperm  |= S_IXUSR;
  301.       }
  302.  
  303.    if (newperm & S_IRGRP)
  304.       {
  305.       newperm |= S_IXGRP;
  306.       }
  307.  
  308.    if (newperm & S_IROTH)
  309.       {
  310.       newperm |= S_IXOTH;
  311.       }
  312.    }
  313.  
  314. if (dstat->st_uid == 0 && (dstat->st_mode & S_ISUID))
  315.    {
  316.    if (newperm & S_ISUID)
  317.       {
  318.       if (! IsItemIn(VSETUIDLIST,file))
  319.          {
  320.          if (amroot)
  321.         {
  322.         sprintf(OUTPUT,"NEW SETUID root PROGRAM %s\n",file);
  323.         CfLog(cfinform,OUTPUT,"");
  324.         }
  325.          PrependItem(&VSETUIDLIST,file,NULL);
  326.          }
  327.       }
  328.    else
  329.       {
  330.       switch (action)
  331.          {
  332.          case fixall:
  333.          case fixdirs:
  334.          case fixplain:  sprintf(OUTPUT,"Removing setuid (root) flag from %s...\n\n",file);
  335.                      CfLog(cfinform,OUTPUT,"");
  336.              
  337.                      if (ptr != NULL)
  338.                             {
  339.                             AddMultipleClasses(ptr->defines);
  340.                             }
  341.                          break;
  342.          case warnall:
  343.          case warndirs:
  344.          case warnplain: if (amroot)
  345.                         {
  346.                               sprintf(OUTPUT,"WARNING setuid (root) flag on %s...\n\n",file);
  347.                 CfLog(cferror,OUTPUT,"");
  348.                         }
  349.                          break;
  350.  
  351.          default:        break;
  352.          }
  353.       }
  354.    }
  355.  
  356. if (dstat->st_uid == 0 && (dstat->st_mode & S_ISGID))
  357.    {
  358.    if (newperm & S_ISGID)
  359.       {
  360.       if (! IsItemIn(VSETUIDLIST,file))
  361.          {
  362.          if (S_ISDIR(dstat->st_mode))
  363.             {
  364.             /* setgid directory */
  365.             }
  366.          else
  367.             {
  368.             if (amroot)
  369.            {
  370.            sprintf(OUTPUT,"NEW SETGID root PROGRAM %s\n",file);
  371.            CfLog(cferror,OUTPUT,"");
  372.            }
  373.             PrependItem(&VSETUIDLIST,file,NULL);
  374.             }
  375.          }
  376.       }
  377.    else
  378.       {
  379.       switch (action)
  380.          {
  381.          case fixall:
  382.          case fixdirs:
  383.          case fixplain: sprintf(OUTPUT,"Removing setgid (root) flag from %s...\n\n",file);
  384.                     CfLog(cfinform,OUTPUT,"");
  385.                     if (ptr != NULL)
  386.                {
  387.                            AddMultipleClasses(ptr->defines);
  388.                }
  389.                     break;
  390.          case warnall:
  391.          case warndirs:
  392.          case warnplain: sprintf(OUTPUT,"WARNING setgid (root) flag on %s...\n\n",file);
  393.                      CfLog(cferror,OUTPUT,"");
  394.                          break;
  395.  
  396.          default:        break;
  397.          }
  398.       }
  399.    }
  400.  
  401. if (CheckOwner(file,action,uidlist,gidlist,dstat))
  402.    {
  403.    if (ptr != NULL)
  404.       {
  405.       AddMultipleClasses(ptr->defines);
  406.       }
  407.    }
  408.  
  409. if ((ptr != NULL) && S_ISREG(dstat->st_mode) && (ptr->checksum == 'm'))
  410.     {
  411.     Debug("Checking MD5 integrity of %s\n",file);
  412.     cfMDFile(file,digest);
  413.     digest[16] = '\0';
  414.     
  415.     if (ChecksumChanged(file,digest,cfsilent,false))
  416.        {
  417.        }
  418.     }
  419.  
  420. if (S_ISLNK(dstat->st_mode))             /* No point in checking permission on a link */
  421.    {
  422.    KillOldLink(file);
  423.  
  424.    if (ptr != NULL)
  425.       {
  426.       AddMultipleClasses(ptr->defines);
  427.       }
  428.    return;
  429.    }
  430.  
  431. if (stat(file,dstat) == -1)
  432.    {
  433.    sprintf(OUTPUT,"Can't stat file %s while looking at permissions (was not copied?)\n",file);
  434.    CfLog(cfverbose,OUTPUT,"stat");
  435.    return;
  436.    }
  437.  
  438. if (CheckACLs(file,action,acl_aliases))
  439.    {
  440.    if (ptr != NULL)
  441.       {
  442.       AddMultipleClasses(ptr->defines);
  443.       }
  444.    }
  445.  
  446. #ifndef HAVE_CHFLAGS
  447. if (((newperm & 07777) == (dstat->st_mode & 07777)) && (action != touch))    /* file okay */
  448.    {
  449.    Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
  450.    return;
  451.    }
  452. #else
  453. if ((newperm & 07777) == (dstat->st_mode & 07777))    /* file okay */
  454.    {
  455.    Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777));
  456.    fixmode = false;
  457.    }
  458. #endif 
  459.  
  460. if (fixmode)
  461.    {
  462.    Debug("Trying to fix mode...\n"); 
  463.    
  464.    switch (action)
  465.       {
  466.       case linkchildren:
  467.       
  468.       case warnplain:
  469.       if (S_ISREG(dstat->st_mode))
  470.          {
  471.          sprintf(OUTPUT,"%s has permission %o\n",file,dstat->st_mode & 07777);
  472.          CfLog(cferror,OUTPUT,"");
  473.          sprintf(OUTPUT,"[should be %o]\n",newperm & 07777);
  474.          CfLog(cferror,OUTPUT,"");
  475.          }
  476.       break;
  477.       case warndirs:
  478.       if (S_ISDIR(dstat->st_mode))
  479.          {
  480.          sprintf(OUTPUT,"%s has permission %o\n",file,dstat->st_mode & 07777);
  481.          CfLog(cferror,OUTPUT,"");
  482.          sprintf(OUTPUT,"[should be %o]\n",newperm & 07777);
  483.          CfLog(cferror,OUTPUT,"");
  484.          }
  485.       break;
  486.       case warnall:   
  487.       sprintf(OUTPUT,"%s has permission %o\n",file,dstat->st_mode & 07777);
  488.       CfLog(cferror,OUTPUT,"");
  489.       sprintf(OUTPUT,"[should be %o]\n",newperm & 07777);
  490.       CfLog(cferror,OUTPUT,"");
  491.       break;
  492.       
  493.       case fixplain:
  494.       if (S_ISREG(dstat->st_mode))
  495.          {
  496.          if (! DONTDO)
  497.         {
  498.         if (chmod (file,newperm & 07777) == -1)
  499.            {
  500.            sprintf(OUTPUT,"chmod failed on %s\n",file);
  501.            CfLog(cferror,OUTPUT,"chmod");
  502.            break;
  503.            }
  504.         }
  505.          
  506.          sprintf(OUTPUT,"%s had permission %o, changed it to %o\n",
  507.              file,dstat->st_mode & 07777,newperm & 07777);
  508.          CfLog(cfinform,OUTPUT,"");
  509.          
  510.          if (ptr != NULL)
  511.         {
  512.         AddMultipleClasses(ptr->defines);
  513.         }
  514.          }
  515.       break;
  516.       
  517.       case fixdirs:
  518.       if (S_ISDIR(dstat->st_mode))
  519.          {
  520.          if (! DONTDO)
  521.         {
  522.         if (chmod (file,newperm & 07777) == -1)
  523.            {
  524.            sprintf(OUTPUT,"chmod failed on %s\n",file);
  525.            CfLog(cferror,OUTPUT,"chmod");
  526.            break;
  527.            }
  528.         }
  529.          
  530.          sprintf(OUTPUT,"%s had permission %o, changed it to %o\n",
  531.              file,dstat->st_mode & 07777,newperm & 07777);
  532.          CfLog(cfinform,OUTPUT,"");
  533.          
  534.          if (ptr != NULL)
  535.         {
  536.         AddMultipleClasses(ptr->defines);
  537.         }
  538.          }
  539.       break;
  540.       
  541.       case fixall:
  542.       if (! DONTDO)
  543.          {
  544.          if (chmod (file,newperm & 07777) == -1)
  545.         {
  546.         sprintf(OUTPUT,"chmod failed on %s\n",file);
  547.         CfLog(cferror,OUTPUT,"chmod");
  548.         break;
  549.         }
  550.          }
  551.       
  552.       sprintf(OUTPUT,"%s had permission %o, changed it to %o\n",
  553.           file,dstat->st_mode & 07777,newperm & 07777);
  554.       CfLog(cfinform,OUTPUT,"");
  555.       
  556.       if (ptr != NULL)
  557.          {
  558.          AddMultipleClasses(ptr->defines);
  559.          }
  560.       break;
  561.       
  562.       case touch:
  563.       if (! DONTDO)
  564.          {
  565.          if (chmod (file,newperm & 07777) == -1)
  566.         {
  567.         sprintf(OUTPUT,"chmod failed on %s\n",file);
  568.         CfLog(cferror,OUTPUT,"chmod");
  569.         break;
  570.         }
  571.          utime (file,NULL);
  572.          }
  573.       if (ptr != NULL)
  574.          {
  575.          AddMultipleClasses(ptr->defines);
  576.          }
  577.       break;
  578.       
  579.       default:     FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n");
  580.       }
  581.    }
  582.  
  583. #if defined HAVE_CHFLAGS  /* BSD special flags */
  584.  
  585. if (ptr != NULL)
  586.    {
  587.    newflags = (dstat->st_flags & CHFLAGS_MASK) ;
  588.    newflags |= ptr->plus_flags;
  589.    newflags &= ~(ptr->minus_flags);
  590.    
  591.    if ((newflags & CHFLAGS_MASK) == (dstat->st_flags & CHFLAGS_MASK))    /* file okay */
  592.       {
  593.       Debug("File okay, flags = %o, current = %o\n",(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
  594.       }
  595.    else
  596.       {
  597.       Debug("Fixing %s, newflags = %o, flags = %o\n",file,(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK));
  598.       
  599.       switch (action)
  600.      {
  601.      case linkchildren:
  602.          
  603.      case warnplain:
  604.          if (S_ISREG(dstat->st_mode))
  605.         {
  606.         sprintf(OUTPUT,"%s has flags %o\n",file,dstat->st_flags & CHFLAGS_MASK);
  607.         CfLog(cferror,OUTPUT,"");
  608.         sprintf(OUTPUT,"[should be %o]\n",newflags & CHFLAGS_MASK);
  609.         CfLog(cferror,OUTPUT,"");
  610.         }
  611.          break;
  612.      case warndirs:
  613.          if (S_ISDIR(dstat->st_mode))
  614.         {
  615.         sprintf(OUTPUT,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK);
  616.         CfLog(cferror,OUTPUT,"");
  617.         sprintf(OUTPUT,"[should be %o]\n",newflags & CHFLAGS_MASK);
  618.         CfLog(cferror,OUTPUT,"");
  619.         }
  620.          break;
  621.      case warnall:
  622.          sprintf(OUTPUT,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK);
  623.          CfLog(cferror,OUTPUT,"");
  624.          sprintf(OUTPUT,"[should be %o]\n",newflags & CHFLAGS_MASK);
  625.          CfLog(cferror,OUTPUT,"");
  626.          break;
  627.          
  628.      case fixplain:
  629.          
  630.          if (S_ISREG(dstat->st_mode))
  631.         {
  632.         if (! DONTDO)
  633.            {
  634.            if (chflags (file,newflags & CHFLAGS_MASK) == -1)
  635.               {
  636.               sprintf(OUTPUT,"chflags failed on %s\n",file);
  637.               CfLog(cferror,OUTPUT,"chflags");
  638.               break;
  639.               }
  640.            }
  641.         
  642.         sprintf(OUTPUT,"%s had flags %o, changed it to %o\n",
  643.             file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
  644.         CfLog(cfinform,OUTPUT,"");
  645.         
  646.         if (ptr != NULL)
  647.            {
  648.            AddMultipleClasses(ptr->defines);
  649.            }
  650.         }
  651.          break;
  652.          
  653.      case fixdirs:
  654.          if (S_ISDIR(dstat->st_mode))
  655.         {
  656.         if (! DONTDO)
  657.            {
  658.            if (chflags (file,newflags & CHFLAGS_MASK) == -1)
  659.               {
  660.               sprintf(OUTPUT,"chflags failed on %s\n",file);
  661.               CfLog(cferror,OUTPUT,"chflags");
  662.               break;
  663.               }
  664.            }
  665.         
  666.         sprintf(OUTPUT,"%s had flags %o, changed it to %o\n",
  667.             file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
  668.         CfLog(cfinform,OUTPUT,"");
  669.         
  670.         if (ptr != NULL)
  671.            {
  672.            AddMultipleClasses(ptr->defines);
  673.            }
  674.         }
  675.          break;
  676.          
  677.       case fixall:
  678.       if (! DONTDO)
  679.          {
  680.          if (chflags (file,newflags & CHFLAGS_MASK) == -1)
  681.         {
  682.         sprintf(OUTPUT,"chflags failed on %s\n",file);
  683.         CfLog(cferror,OUTPUT,"chflags");
  684.         break;
  685.         }
  686.          }
  687.       
  688.       sprintf(OUTPUT,"%s had flags %o, changed it to %o\n",
  689.           file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK);
  690.       CfLog(cfinform,OUTPUT,"");
  691.       
  692.       if (ptr != NULL)
  693.          {
  694.          AddMultipleClasses(ptr->defines);
  695.          }
  696.       break;
  697.       
  698.       case touch:
  699.       if (! DONTDO)
  700.          {
  701.          if (chflags (file,newflags & CHFLAGS_MASK) == -1)
  702.         {
  703.         sprintf(OUTPUT,"chflags failed on %s\n",file);
  704.         CfLog(cferror,OUTPUT,"chflags");
  705.         break;
  706.         }
  707.          utime (file,NULL);
  708.          }
  709.       if (ptr != NULL)
  710.          {
  711.          AddMultipleClasses(ptr->defines);
  712.          }
  713.       break;
  714.       
  715.      default:     FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n");
  716.      }
  717.       }
  718.    }
  719. #endif
  720.  
  721.  
  722. Debug("CheckExistingFile(Done)\n"); 
  723. }
  724.  
  725. /*********************************************************************/
  726.  
  727. CheckCopiedFile(file,plus,minus,action,uidlist,gidlist,dstat,sstat,ptr,acl_aliases)
  728.  
  729. char *file;
  730. mode_t plus,minus;
  731. struct UidList *uidlist;
  732. struct GidList *gidlist;
  733. enum fileactions action;
  734. struct stat *dstat;
  735. struct stat *sstat;
  736. struct File *ptr;
  737. struct Item *acl_aliases;
  738.  
  739. { mode_t newplus,newminus;
  740.  
  741.  /* plus/minus must be relative to source file, not to
  742.     perms of newly created file! */
  743.  
  744. Debug("CheckCopiedFile(%s)\n",file); 
  745.  
  746. if ((plus == 0) && (minus == 0))
  747.     {
  748.     newplus = sstat->st_mode & 07777 | plus;
  749.     newminus = ~(sstat->st_mode & 07777 & ~minus) & 07777;
  750.     CheckExistingFile(file,newplus,newminus,fixall,uidlist,gidlist,dstat,NULL,acl_aliases);
  751.     }
  752.  else
  753.     {
  754.     CheckExistingFile(file,plus,minus,fixall,uidlist,gidlist,dstat,NULL,acl_aliases);
  755.     }
  756. }
  757.  
  758. /*********************************************************************/
  759.  
  760. CheckOwner(file,action,uidlist,gidlist,statbuf)
  761.  
  762. char *file;
  763. enum fileactions action;
  764. struct UidList *uidlist;
  765. struct GidList *gidlist;
  766. struct stat *statbuf;
  767.  
  768. { struct passwd *pw;
  769.   struct group *gp;
  770.   struct UidList *ulp;
  771.   struct GidList *glp;
  772.   short uidmatch = false, gidmatch = false;
  773.   uid_t uid = (uid_t)-1; 
  774.   gid_t gid = (gid_t)-1;
  775.  
  776. Debug("CheckOwner: %d\n",statbuf->st_uid);
  777.   
  778. for (ulp = uidlist; ulp != NULL; ulp=ulp->next)
  779.    {
  780.    Debug(" uid %d\n",ulp->uid);
  781.  
  782.    if (ulp->uid == (uid_t) -1 || statbuf->st_uid == ulp->uid)   /* -1 matches anything */
  783.       {
  784.       uid = ulp->uid;
  785.       uidmatch = true;
  786.       break;
  787.       }
  788.    }
  789.  
  790. for (glp = gidlist; glp != NULL; glp=glp->next)
  791.    {
  792.    if (glp->gid == (gid_t) -1 || statbuf->st_gid == glp->gid)  /* -1 matches anything */
  793.       {
  794.       gid = glp->gid;
  795.       gidmatch = true;
  796.       break;
  797.       }
  798.    }
  799.  
  800.  
  801. if (uidmatch && gidmatch)
  802.    {
  803.    return false;
  804.    }
  805. else
  806.    {
  807.    if ((! uidmatch) && (uidlist != NULL))
  808.       {
  809.       uid = uidlist->uid;    /* default is first item in list */
  810.       }
  811.  
  812.    if ((! gidmatch) && (gidlist != NULL))
  813.       {
  814.       gid = gidlist->gid;
  815.       }
  816.  
  817.    if (S_ISLNK(statbuf->st_mode) && (action == fixdirs || action == fixplain))
  818.       {
  819.       Debug2("File %s incorrect type (link), skipping...\n",file);
  820.       return false;
  821.       }
  822.  
  823.    if ((S_ISREG(statbuf->st_mode) && action == fixdirs) || (S_ISDIR(statbuf->st_mode) && action == fixplain))
  824.       {
  825.       Debug2("File %s incorrect type, skipping...\n",file);
  826.       return false;
  827.       }
  828.  
  829.    switch (action)
  830.       {
  831.       case fixplain:
  832.       case fixdirs:
  833.       case fixall: 
  834.       case touch:
  835.                   if (VERBOSE || DEBUG || D2)
  836.                      {
  837.                      if (uid == (uid_t) -1 && gid == (gid_t) -1)
  838.                         {
  839.                         printf("%s:   touching %s\n",VPREFIX,file);
  840.                         }
  841.                      else
  842.                         {
  843.                         if (uid != (uid_t) -1)
  844.                            {
  845.                            sprintf(OUTPUT,"  (Change owner to uid %d if possible)\n",uid);
  846.                            CfLog(cfinform,OUTPUT,"");
  847.                            }
  848.  
  849.                         if (gid != (gid_t) -1)
  850.                            {
  851.                            sprintf(OUTPUT,"  (Change group to gid %d if possible)\n",gid);
  852.                            CfLog(cfinform,OUTPUT,"");
  853.                            }
  854.                         }
  855.                      }
  856.  
  857.                   if (! DONTDO && S_ISLNK(statbuf->st_mode))
  858.                      {
  859. #ifdef HAVE_LCHOWN
  860.              Debug("Using LCHOWN function\n");
  861.                      if (lchown(file,uid,gid) == -1)
  862.                         {
  863.                         sprintf(OUTPUT,"Cannot set ownership on link %s!\n",file);
  864.                         CfLog(cflogonly,OUTPUT,"lchown");
  865.                         }
  866.              else
  867.             {
  868.             return true;
  869.             }
  870. #endif
  871.                      }
  872.                   else if (! DONTDO)
  873.                      {
  874.                      if (chown(file,uid,gid) == -1)
  875.                         {
  876.                         sprintf(OUTPUT,"Cannot set ownership on file %s!\n",file);
  877.                         CfLog(cflogonly,OUTPUT,"chown");
  878.                         }
  879.              else
  880.             {
  881.             return true;
  882.             }
  883.                      }
  884.                   break;
  885.  
  886.       case linkchildren:
  887.       case warnall: 
  888.       case warndirs:
  889.       case warnplain:
  890.                   if ((pw = getpwuid(statbuf->st_uid)) == NULL)
  891.                      {
  892.                      sprintf(OUTPUT,"File %s is not owned by anybody in the passwd database\n",file);
  893.              CfLog(cferror,OUTPUT,"");
  894.                      sprintf(OUTPUT,"(uid = %d,gid = %d)\n",statbuf->st_uid,statbuf->st_gid);
  895.              CfLog(cferror,OUTPUT,"");
  896.                      break;
  897.                      }
  898.  
  899.                   if ((gp = getgrgid(statbuf->st_gid)) == NULL)
  900.                      {
  901.                      sprintf(OUTPUT,"File %s is not owned by any group in group database\n",file);
  902.              CfLog(cferror,OUTPUT,"");
  903.                      break;
  904.                      }
  905.  
  906.                   sprintf(OUTPUT,"File %s is owned by [%s], group [%s]\n",file,pw->pw_name,gp->gr_name);
  907.           CfLog(cferror,OUTPUT,"");
  908.                   break;
  909.       }
  910.    }
  911. return false; 
  912. }
  913.  
  914.  
  915. /*********************************************************************/
  916.  
  917. CheckHomeSubDir(testpath,tidypath,recurse)
  918.  
  919. char *testpath, *tidypath;
  920. int recurse;
  921.  
  922. { char *sp, *subdirstart, *sp1, *sp2;
  923.   char buffer[bufsize];
  924.   int homelen;
  925.  
  926. if (strncmp(tidypath,"home/",5) == 0)
  927.    {
  928.    strcpy(buffer,testpath);
  929.  
  930.    for (ChopLastNode(buffer); strlen(buffer) != 0; ChopLastNode(buffer))
  931.      {
  932.      if (IsHomeDir(buffer))
  933.         {
  934.         break;
  935.         }
  936.      }
  937.  
  938.    homelen = strlen(buffer);
  939.  
  940.    if (homelen == 0)   /* No homedir */
  941.       {
  942.       return false;
  943.       }
  944.  
  945.    Debug2("CheckHomeSubDir(%s,%s)\n",testpath,tidypath);
  946.  
  947.    subdirstart = tidypath + 4;                                   /* Ptr to start of subdir */
  948.  
  949.    strcpy(buffer,testpath);
  950.  
  951.    ChopLastNode(buffer);                                         /* Filename only */
  952.  
  953.    for (sp1 = buffer + homelen +1; *sp1 != '/' && *sp1 != '\0'; sp1++) /* skip user name dir */
  954.       {
  955.       }
  956.  
  957.    sp2 = subdirstart;
  958.  
  959.    if (strncmp(sp1,sp2,strlen(sp2)) != 0)
  960.       {
  961.       return false;
  962.       } 
  963.  
  964.    Debug2("CheckHomeSubDir(true)\n");
  965.    return(true);
  966.    }
  967.  
  968. return true;
  969. }
  970.  
  971. /**************************************************************/
  972.  
  973. FileIsNewer(file1,file2)
  974.  
  975. /* True if file2 is newer than file 1 */
  976.  
  977. char *file1, *file2;
  978.  
  979. { struct stat statbuf1, statbuf2;
  980.  
  981. if (stat(file2,&statbuf2) == -1)
  982.    {
  983.    CfLog(cferror,"","stat");
  984.    return false;
  985.    }
  986.  
  987. if (stat(file1,&statbuf1) == -1)
  988.    {
  989.    CfLog(cferror,"","stat");
  990.    return true;
  991.    }
  992.  
  993. if (statbuf1.st_mtime < statbuf2.st_mtime)
  994.    {
  995.    return true;
  996.    }
  997. else
  998.    {
  999.    return false;
  1000.    }
  1001. }
  1002.  
  1003.  
  1004. /*********************************************************************/
  1005. /* Ignore is used by files and tidy modules                          */
  1006. /*********************************************************************/
  1007.  
  1008. IgnoreFile (pathto,name,ignores)
  1009.  
  1010. char *pathto, *name;
  1011. struct Item *ignores;
  1012.  
  1013. { struct Item *ip;
  1014.  
  1015. Debug("IgnoreFile(%s)\n",name);
  1016.  
  1017. if (name == NULL || strlen(name) == 0)
  1018.    {
  1019.    return false;
  1020.    }
  1021.  
  1022. strcpy(VBUFF,pathto);
  1023. AddSlash(VBUFF);
  1024. strcat(VBUFF,name);
  1025.  
  1026. if (ignores != NULL)
  1027.    {
  1028.    if (IsWildItemIn(ignores,VBUFF))
  1029.       {
  1030.       Debug("cfengine: Ignoring private abs path [%s][%s]\n",pathto,name);
  1031.       return true;
  1032.       }
  1033.  
  1034.    if (IsWildItemIn(ignores,name))
  1035.       {
  1036.       Debug("cfengine: Ignoring private pattern [%s][%s]\n",pathto,name);
  1037.       return true;
  1038.       }
  1039.    }
  1040.  
  1041. for (ip = VIGNORE; ip != NULL; ip=ip->next)
  1042.    {
  1043.    if (IsExcluded(ip->classes))
  1044.       {
  1045.       continue;
  1046.       }
  1047.  
  1048.    if (*(ip->name) == '/')
  1049.       {
  1050.       if (strcmp(VBUFF,ip->name) == 0)
  1051.          {
  1052.          Debug("cfengine: Ignoring global abs path [%s][%s]\n",pathto,name);
  1053.          return true;
  1054.          }
  1055.       }
  1056.    else
  1057.       {
  1058.       if (WildMatch(ip->name,name))
  1059.          {
  1060.          Debug("cfengine: Ignoring global pattern [%s][%s]\n",pathto,name);
  1061.          return true;
  1062.          }
  1063.       }
  1064.    }
  1065.  
  1066. return false;
  1067. }
  1068.  
  1069.  
  1070.  
  1071.